package cn.lg.soar.boot.fc.service.impl;

import cn.lg.soar.boot.fc.entity.*;
import cn.lg.soar.boot.fc.entity.importExcel.CampusIo;
import cn.lg.soar.boot.fc.entity.vo.CampusEasyVo;
import cn.lg.soar.boot.fc.entity.vo.CampusVo;
import cn.lg.soar.boot.fc.entity.vo.FcTreeVo;
import cn.lg.soar.boot.fc.service.BuildingService;
import cn.lg.soar.boot.fc.service.FloorService;
import cn.lg.soar.boot.fc.service.UnitService;
import cn.lg.soar.common.data.msg.I18n;
import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.model.PageQuery;
import cn.lg.soar.common.model.PageResult;
import cn.lg.soar.core.util.easyexcel.ExcelUtil;
import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.boot.fc.mapper.CampusMapper;
import cn.lg.soar.boot.fc.service.CampusService;
import cn.lg.soar.database.query.QueryParams;
import cn.lg.soar.database.query.SqueryWapper;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 校区表
 * @author lhp
 * @since 2024-12-25
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Service
public class CampusServiceImpl extends BaseServiceImpl<CampusMapper, Campus> implements CampusService {

    // 楼栋信息
    @Autowired
    private BuildingService buildingService;

    // 单元信息
    @Autowired
    private UnitService unitService;

    // 楼层信息
    @Autowired
    private FloorService floorService;

    @Override
    public List<CampusVo> getListVo() {

        List<CampusVo> listVo = new ArrayList<>();
        List<Campus> listT = list(Wrappers.<Campus>lambdaQuery());

        listT.forEach(item-> {
            CampusVo campusVo = new CampusVo();
            BeanUtils.copyProperties(item, campusVo);
            listVo.add(campusVo);
        });
        return listVo;
    }

    @Override
    public Campus getData(Long id) {
        if (Objects.isNull(id)) {
            return new Campus();
        }

        Campus campus = this.getOne(Wrappers.<Campus>lambdaQuery().eq(Campus::getId, id));
        if (null == campus) {
            campus = new Campus();
        }
        return campus;

    }

    @Override
    public CampusVo getVoData(Long id) {
        CampusVo campusVo = new CampusVo();
        if (Objects.isNull(id)) {
            return campusVo;
        }
        Campus campus = this.getData(id);
        BeanUtils.copyProperties(campus, campusVo);
        return campusVo;
    }

    /**
     * 可以单独摘出来一个简单的vo
     * @param id
     * @return
     */
    @Override
    public CampusEasyVo getEasyVoData(Long id) {
        CampusEasyVo campusEasyVo = new CampusEasyVo();
        if (Objects.isNull(id)) {
            return campusEasyVo;
        }
        Campus campus = this.getData(id);
        BeanUtils.copyProperties(campus, campusEasyVo);
        return campusEasyVo;
    }

    @Override
    public PageResult<FcTreeVo> queryResultVo(PageQuery pageQuery, QueryParams params) {

        PageResult<FcTreeVo> pageResultVo = new PageResult<>();

        SqueryWapper<Campus> squeryWapper = new SqueryWapper<>(Campus.class);
        PageResult<Campus> pageResult = squeryWapper.query(this, pageQuery, params);

        // 对象拷贝
        BeanUtils.copyProperties(pageQuery, pageResultVo);

        // 返回vo
        List<FcTreeVo> listVo = new ArrayList<>();

        // 校区
        pageResult.getList().forEach(item-> {

            FcTreeVo fcTreeVo = new FcTreeVo();
            BeanUtils.copyProperties(item, fcTreeVo);

            // 校区父节点
            fcTreeVo.setParentId(("0"));

            // "校区id-楼栋id-单元id-楼层id"
            String id = item.getId() + "-0-0-0";
            fcTreeVo.setId(id);

            listVo.add(fcTreeVo);
            QueryParams buildParams = new QueryParams();
            List<String> buildingF = new ArrayList<>();
            buildingF.add("campusId-eq~" + item.getId());
            buildParams.setF(buildingF);
            List<Building> buildingList = buildingService.getListByCampusId(buildParams);

            // 楼栋信息
            buildingList.forEach(bItem-> {

                FcTreeVo fcTreeVoBuild = new FcTreeVo();
                BeanUtils.copyProperties(bItem, fcTreeVoBuild);

                // 父节点
                fcTreeVoBuild.setParentId((item.getId() + "-0-0-0"));
                // "校区id-楼栋id-单元id-楼层id"
                fcTreeVoBuild.setId(item.getId() + "-" + bItem.getId() + "-0-0");
                listVo.add(fcTreeVoBuild);
                // 单元信息
                QueryParams unitParams = new QueryParams();
                List<String> unitF = new ArrayList<>();
                unitF.add("campusId-eq~" + item.getId());
                unitF.add("buildingId-eq~" + bItem.getId());
                unitParams.setF(unitF);
                List<Unit> unitList = unitService.getListByOtherId(unitParams);

                // 单元信息
                unitList.forEach(uItem-> {
                    FcTreeVo fcTreeVoUnit = new FcTreeVo();

                    BeanUtils.copyProperties(uItem, fcTreeVoUnit);

                    // 父节点
                    fcTreeVoUnit.setParentId((item.getId() + "-" + bItem.getId() + "-0-0"));
                    // "校区id-楼栋id-单元id-楼层id"
                    fcTreeVoUnit.setId(item.getId() + "-" + bItem.getId() + "-" + uItem.getId() + "-0");
                    listVo.add(fcTreeVoUnit);

                    QueryParams floorParams = new QueryParams();
                    List<String> floorF = new ArrayList<>();
                    floorF.add("campusId-eq~" + item.getId());
                    floorF.add("buildingId-eq~" + bItem.getId());
                    floorF.add("unitId-eq~" + uItem.getId());
                    floorParams.setF(floorF);
                    List<Floor> floorList = floorService.getListByOtherId(floorParams);
                    // 楼层信息
                    floorList.forEach(fItem-> {
                        FcTreeVo fcTreeVoFloor = new FcTreeVo();
                        BeanUtils.copyProperties(fItem, fcTreeVoFloor);
                        // 父节点
                        fcTreeVoFloor.setParentId((item.getId() + "-" + bItem.getId() + "-" + uItem.getId() + "-0"));
                        // "校区id-楼栋id-单元id-楼层id"
                        fcTreeVoFloor.setId(item.getId() + "-" + bItem.getId() + "-" + uItem.getId() + "-" + fItem.getId());
                        listVo.add(fcTreeVoFloor);
                    });
                });
            });
        });


        pageResultVo.setList(listVo);
        pageResultVo.setTotal(Long.valueOf(listVo.size()));
        return pageResultVo;
    }

    @Override
    public PageResult<FcTreeVo> queryFirstTreeVo(PageQuery pageQuery, QueryParams params) {

        PageResult<FcTreeVo> pageResultVo = new PageResult<>();

        SqueryWapper<Campus> squeryWapper = new SqueryWapper<>(Campus.class);
        PageResult<Campus> pageResult = squeryWapper.query(this, pageQuery, params);

        // 对象拷贝
        BeanUtils.copyProperties(pageQuery, pageResultVo);

        // 返回vo
        List<FcTreeVo> listVo = new ArrayList<>();

        // 校区
        pageResult.getList().forEach(item-> {

            FcTreeVo fcTreeVo = new FcTreeVo();
            BeanUtils.copyProperties(item, fcTreeVo);
            // 校区父节点
            fcTreeVo.setParentId(("0"));
            fcTreeVo.setId(String.valueOf(item.getId()));
            listVo.add(fcTreeVo);
        });


        pageResultVo.setList(listVo);
        pageResultVo.setTotal(Long.valueOf(listVo.size()));
        return pageResultVo;
    }

    @Override
    public PageResult<JSONObject> queryResultEasyVo(PageQuery pageQuery, QueryParams params) {

        PageResult<JSONObject> pageResultVo = new PageResult<>();

        SqueryWapper<Campus> squeryWapper = new SqueryWapper<>(Campus.class);
        PageResult<Campus> pageResult = squeryWapper.query(this, pageQuery, params);

        // 对象拷贝
        BeanUtils.copyProperties(pageQuery, pageResultVo);

        // 返回vo
        List<JSONObject> listVo = new ArrayList<>();

        // 校区
        pageResult.getList().forEach(item-> {

            // 校区数据json
            JSONObject jsonObject = new JSONObject();
            // "校区id-楼栋id-单元id-楼层id"
            String id = item.getId() + "-0-0-0";
            jsonObject.put("value", id);
            jsonObject.put("label", item.getName());

            // 校区是否有儿子有的话扔进去
            JSONArray jsonArray = new JSONArray();


            QueryParams buildParams = new QueryParams();
            List<String> buildingF = new ArrayList<>();
            buildingF.add("campusId-eq~" + item.getId());
            buildParams.setF(buildingF);
            List<Building> buildingList = buildingService.getListByCampusId(buildParams);

            // 楼栋信息
            buildingList.forEach(bItem-> {

                // 楼栋数据json
                JSONObject jsonObjectBuild = new JSONObject();

                jsonObjectBuild.put("value", item.getId() + "-" + bItem.getId() + "-0-0");
                jsonObjectBuild.put("label", bItem.getName());

                // 楼栋的儿子
                JSONArray jsonArrayBuild = new JSONArray();

                // 单元信息
                QueryParams unitParams = new QueryParams();
                List<String> unitF = new ArrayList<>();
                unitF.add("campusId-eq~" + item.getId());
                unitF.add("buildingId-eq~" + bItem.getId());
                unitParams.setF(unitF);
                List<Unit> unitList = unitService.getListByOtherId(unitParams);

                // 单元信息
                unitList.forEach(uItem-> {
                    // 单元数据json
                    JSONObject jsonObjectUnit = new JSONObject();
                    jsonObjectUnit.put("value", item.getId() + "-" + bItem.getId() + "-" + uItem.getId() + "-0");
                    jsonObjectUnit.put("label", uItem.getName());
                    jsonArrayBuild.add(jsonObjectUnit);
                });
                if (0 < jsonArrayBuild.size()) {
                    jsonObjectBuild.put("children", jsonArrayBuild);
                }
                // 楼栋信息扔进 校区 子对象里
                jsonArray.add(jsonObjectBuild);

            });
            // 校区信息封装结束
            if (0 < jsonArray.size()) {
                jsonObject.put("children", jsonArray);
            }
            listVo.add(jsonObject);
        });

        pageResultVo.setList(listVo);
        return pageResultVo;
    }

    @Override
    public Campus getByName(String name) {
        if (StringUtils.isBlank(name)) {
            return new Campus();
        }
        return this.getFirst(Wrappers.<Campus>lambdaQuery().eq(Campus::getName, name));
    }

    @Override
    public void exportExcel(String filename, QueryParams params, HttpServletResponse resp) {
        SqueryWapper<Campus> squeryWapper = new SqueryWapper<>(Campus.class);

        if (squeryWapper == null) {
            squeryWapper = new SqueryWapper<>(Campus.class);
        }
        QueryWrapper<Campus> wrapper = Wrappers.query();
        squeryWapper.setWhere(params.getF(), wrapper);
        squeryWapper.setSelect(params.getFields(), wrapper);
        squeryWapper.setOrderBy(params.getOrderBy(), wrapper);
        List<Campus> list = new ArrayList<>();
        List<CampusIo> listIo = new ArrayList<>();
        if(params.getF() == null){
            list.add(new Campus());
            listIo.add(new CampusIo());
        }else {
            list = this.list(wrapper);
        }

        list.forEach(item-> {
            CampusIo campusIo = new CampusIo();
            BeanUtils.copyProperties(item, campusIo);
            listIo.add(campusIo);
        });

        if (StringUtils.isBlank(filename)) {
            filename = "校区";
        }
        // 导出
        ExcelUtil.exportExcel(filename, listIo, resp);
    }

    @Override
    public HttpResult<Void> importExcel(MultipartFile files) {

        List<CampusIo> dataList;

        try {
            dataList = EasyExcel.read(files.getInputStream()).head(CampusIo.class).sheet()
                    .doReadSync();
        } catch (Exception e) {
            return HttpResult.fail("B0000", I18n.build("数据格式存在问题，无法读取！"));
        }
        if (0 >= dataList.size()) {
            return HttpResult.fail("B0000", I18n.build("无数据，无法读取！"));
        }

        AtomicInteger successNum = new AtomicInteger();
        AtomicInteger errorNum = new AtomicInteger();

        dataList.forEach(item-> {
            importExcelHelper(item, successNum, errorNum);
        });

        String message = "总数：" + dataList.size() + "; 成功：" + successNum.get() + "; 失败：" + errorNum.get();
        return HttpResult.success("导入成功 " + message);
    }

    @Override
    public HttpResult<Serializable> updateSort(List<Map<String, Integer>> sortedData) {
        if (null == sortedData || 0 >= sortedData.size()) {
            return HttpResult.fail("4000", "排序数据不可为空", "error");
        }

        sortedData.forEach(item-> {

            if (!item.containsKey("id") || !item.containsKey("orders")) {
                return;
            }

            Long id = item.get("id").longValue();;
            int orders = item.get("orders");

            Campus campus = new Campus();
            campus.setId(id);
            campus.setOrders(orders);
            this.updateById(campus);
        });
        return HttpResult.success("排序成功");
    }

    /**
     * 表格导入数据处理
     * @param campusIo
     * @param successNum
     * @param errorNum
     */
    private void importExcelHelper (CampusIo campusIo, AtomicInteger successNum, AtomicInteger errorNum) {

        boolean checkFlag =
                StringUtils.isBlank(campusIo.getName()) || StringUtils.isBlank(campusIo.getAddress()) || StringUtils.isBlank(campusIo.getArea());

        if (checkFlag) {
            errorNum.getAndIncrement();
            return;
        }
        Campus campus = new Campus();
        BeanUtils.copyProperties(campusIo, campus);

        try {
            this.save(campus);
            successNum.getAndIncrement();
        } catch (Exception e) {
            e.printStackTrace();
            errorNum.getAndIncrement();
            return;
        }
    }

}
